package p35_HandlerMapper和HandlerAdapter其3;

import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.resource.CachingResourceResolver;
import org.springframework.web.servlet.resource.EncodedResourceResolver;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import java.util.List;

/**
 * 欢迎页映射器，可以映射资源，也可以映射控制器方法
 * boot提供的
 */
@Configuration
public class _2_WelcomePage{
    public static void main(String[] args) {
        AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

        /**
         * 小结:
         * HandlerMapper接口 负责建立请求与控制器(处理器)之间的映射关系
         *  1.RequestMappingHandlerMapping  (匹配@RequestMapping)
         *  2.WelcomePageHandlerMapping     (/)
         *  3.BeanNameUrlHandlerMapping     (与以/开头的bean名称匹配)
         *  4.RouterFunctionMapping         (函数式，RequestPredicates断言成功，执行HandlerFunction)
         *  5.SimpleUrlHandlerMapping       (静态资源 通配符匹配静态资源)
         * 会根据请求依次从上面的映射器找到处理器(控制器方法)，这也是boot中的顺序
         *
         * HandlerAdapter接口 从HandlerMapper获取handler和控制器方法后，负责对各种各样的handler和控制器方法的适配调用
         *  1.RequestMappingHandlerAdapter  (处理和调用@RequestMapping)
         *      这种涉及参数解析器、返回值处理器，最为复杂
         *  2.SimpleControllerHandlerAdapter (处理Controller接口的控制器)
         *  3.HandlerFunctionAdapter        (处理HandlerFunction函数式接口)
         *  4.HttpRequestHandlerAdapter     (处理HttpRequestHandler接口，静态资源处理)
         * 会根据找到处理器(控制器方法)，逐一调用适配器的support接口，看是不是支持，支持就使用当前适配器来适配和调用
         */
    }

    /**
     * WelcomePageHandlerMapping类是boot提供的，是私有的，所以直接拷贝了一份代码到本目录下
     * WelcomePageHandlerMapping内置了Controller接口的实现类ParameterizableViewController，所以需要SimpleControllerHandlerAdapter来执行处理器
     * ParameterizableViewController,内部逻辑是不执行任何逻辑，仅仅是forward:index.html，转发至index.html,然后又会走前一节的静态资源处理逻辑
     * WelcomePageHandlerMapping这个适配器仅仅映射根路径，并转发请求/index.html，所以需要有一个处理器来接受这个请求
     */
    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext context) {
        //欢迎页资源路径
        Resource resource = context.getResource("classpath:p35/index.html");
        WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(null, context, resource, "/**");
        return welcomePageHandlerMapping;
    }

    @Bean
    public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
        return new SimpleControllerHandlerAdapter();
    }

    //欢迎语转发的请求，被这个处理器处理
    @Bean("/index.html")
    public ResourceHttpRequestHandler handler() {
        ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
        handler.setLocations(List.of(new ClassPathResource("p35/")));
        return handler;
    }
}
